234. 回文链表
234. 回文链表
Similar Question
leading to the advanced question
Solution Tips
方案一: 快慢指针 + 翻转链表 + 回文判断
经典回文判断:
- 翻转之后是否一样
- 从中间开始遍历, 和从头开始遍历结果是一样的
既然是链表, 那当然是经典的找到中间节点, 然后从头开始遍历, 只要是相同的话就是回文链表了
哦哦 想错了, 应该是找到中间节点的过程中, 建立 prev 指针, 构建局部的双向链表, 然后遍历的时候取消掉 prev 指针就好了
/**
* @param {ListNode} head
* @return {boolean}
*/
const reverseList = (head) => {
let prev = null;
let curr = head;
while (curr !== null) {
let nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
const endOfFirstHalf = (head) => {
let fast = head;
let slow = head;
while (fast.next !== null && fast.next.next !== null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
var isPalindrome = function(head) {
if (head == null) return true;
// 找到前半部分链表的尾节点并反转后半部分链表
const firstHalfEnd = endOfFirstHalf(head);
const secondHalfStart = reverseList(firstHalfEnd.next);
// 判断是否回文
let p1 = head;
let p2 = secondHalfStart;
let result = true;
while (result && p2 != null) {
if (p1.val != p2.val) result = false;
p1 = p1.next;
p2 = p2.next;
}
// 还原链表并返回结果
firstHalfEnd.next = reverseList(secondHalfStart);
return result;
};
方案二: 递归
后序遍历, 可以做到反向遍历节点
在外部维护一个前序遍历的变量, 做到双向遍历链表节点
let frontPointer;
const recursivelyCheck = (currentNode) => {
if (currentNode !== null) {
if (!recursivelyCheck(currentNode.next)) {
return false;
}
if (currentNode.val !== frontPointer.val) {
return false;
}
frontPointer = frontPointer.next;
}
return true;
}
var isPalindrome = function(head) {
frontPointer = head;
return recursivelyCheck(head);
};